package cn.lingyangwl.framework.tool.crypto.asymmetric;

import cn.lingyangwl.framework.tool.core.CollectionUtils;
import org.reflections.Reflections;

import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author shenguangyang
 */
public class AsymmetricCryptoManager {
    protected final Map<AsymmetricCryptoType, BaseAsymmetricCrypto> CRYPTO = new ConcurrentHashMap<>();

    public BaseAsymmetricCrypto getAsymmetricCrypto(AsymmetricCryptoType type) {
        BaseAsymmetricCrypto baseAsymmetricCrypto = CRYPTO.get(type);
        if (Objects.isNull(baseAsymmetricCrypto)) {
            synchronized (this) {
                baseAsymmetricCrypto = CRYPTO.get(type);
                if (Objects.isNull(baseAsymmetricCrypto)) {
                    Reflections reflections = new Reflections(BaseAsymmetricCrypto.class.getPackage().getName());
                    Set<Class<? extends BaseAsymmetricCrypto>> subTypes = reflections.getSubTypesOf(BaseAsymmetricCrypto.class);
                    if (CollectionUtils.isEmpty(subTypes)) {
                        throw new RuntimeException(type.name() + " not supported");
                    }
                    BaseAsymmetricCrypto asymmetricCrypto = subTypes.stream().map(x -> {
                        try {
                            return x.newInstance();
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }).filter(x -> x.type() == type).findFirst().orElseThrow(() -> new RuntimeException(type.name() + " not found"));
                    CRYPTO.put(type, asymmetricCrypto);
                }
            }
        }
        return CRYPTO.get(type);
    }
}
